import { ResponseBody, ResponseCode } from '@/utils/ResponseCode';
import {
  Body,
  Controller,
  Delete,
  Get,
  HttpException,
  HttpStatus,
  Param,
  Post,
  Put,
  Req,
  Session,
  UseGuards,
} from '@nestjs/common';
import { PermissionService } from './permission.service';
import { Permission as PermissionEntity } from '@/entity/Permission';
import { createPermissionTreeByPath } from '@/utils/createPermissionTreeByPath';
import {
  CreatePermissionRequest,
  UpdatePermissionRequest,
} from './dto/request.dto';
import { Request as HttpRequest } from 'express';
import { SessionType } from '@/types';
import { UserService } from '../user/user.service';
import { SessionGuard } from '@/guard/session.guard';

@UseGuards(SessionGuard)
@Controller('permission')
export class PermissionController {
  constructor(
    private readonly permissionService: PermissionService,
    private readonly userService: UserService,
  ) {}

  // 获取权限树
  @Get()
  async getPermissionTree(
    @Req() request: HttpRequest,
    @Session() session: SessionType,
  ) {
    // 接口鉴权
    await this.userService.verifyPermission(request, session.username);
    // 拉取所有的权限
    const permissionEntityList = await this.permissionService.findAll();
    const permissionTree = createPermissionTreeByPath(permissionEntityList);
    return new ResponseBody<{
      permissionTree: PermissionEntity[];
      permissionList: PermissionEntity[];
    }>({
      data: {
        permissionTree,
        permissionList: permissionEntityList,
      },
      message: '获取权限列表成功',
    });
  }

  // 创建对应的权限
  @Post()
  async createPermission(
    @Body() requestBody: CreatePermissionRequest,
    @Req() request: HttpRequest,
    @Session() session: SessionType,
  ) {
    // 接口鉴权
    await this.userService.verifyPermission(request, session.username);
    const { parentId, ...toAddPermission } = requestBody;
    let toAddPermissionIdPath = '';
    // 如果不是添加一级菜单
    if (parentId !== 0) {
      const parentPermissionEntity = await this.permissionService.findOneBy({
        id: parentId,
      });
      // 父级权限不存在报错
      if (!parentPermissionEntity || parentPermissionEntity.funcType === '2') {
        return new ResponseBody({
          code: ResponseCode.Fail,
          message: '父级不存在或者父级类型为非菜单',
        });
      }
      toAddPermissionIdPath = `${parentPermissionEntity.idPath}/${parentPermissionEntity.id}`;
    }
    // 当前权限名称是否重复
    const oldPermissionEntity = await this.permissionService.findOneBy({
      name: toAddPermission.name,
    });
    if (oldPermissionEntity) {
      return new ResponseBody({
        code: ResponseCode.Fail,
        message: '权限名称重复，创建失败',
      });
    }
    const permissionEntity = await this.permissionService.create({
      ...toAddPermission,
      idPath: toAddPermissionIdPath,
    });
    return new ResponseBody<number>({
      message: '创建权限成功',
      data: permissionEntity.id,
    });
  }

  @Put(':id')
  async updatePermissionById(
    @Param('id') permissionId: number,
    @Body() requestBody: UpdatePermissionRequest,
    @Req() request: HttpRequest,
    @Session() session: SessionType,
  ) {
    // 接口鉴权
    await this.userService.verifyPermission(request, session.username);
    const { parentId, ...toUpdatePermission } = requestBody;
    const oldPermissionEntity = await this.permissionService.findOneBy({
      name: toUpdatePermission.name,
    });
    if (
      oldPermissionEntity &&
      oldPermissionEntity.id !== Number(permissionId)
    ) {
      return new ResponseBody({
        code: ResponseCode.Fail,
        message: '权限名称重复，更新失败',
        data: oldPermissionEntity,
      });
    }
    // 不仅仅是要更新当前的权限点，还是要更新所有的子集的权限
    try {
      await this.permissionService.updatePermissionById(
        permissionId,
        toUpdatePermission,
        parentId,
      );
      return new ResponseBody('权限修改成功');
    } catch (error) {
      console.log(error);
      // 事务抛出错误的兜底
      throw new HttpException(
        {
          message: error,
          code: ResponseCode.Fail,
          data: null,
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  @Delete(':id')
  async deletePermissionById(
    @Param('id') permissionId: number,
    @Req() request: HttpRequest,
    @Session() session: SessionType,
  ) {
    // 接口鉴权
    await this.userService.verifyPermission(request, session.username);
    // 删除权限及其所有子权限，以及所有权限的角色权限关系
    try {
      await this.permissionService.deletePermissionById(Number(permissionId));
      return new ResponseBody('权限删除成功');
    } catch (error) {
      console.log(error);
      // 事务抛出错误的兜底
      throw new HttpException(
        {
          message: error,
          code: ResponseCode.Fail,
          data: null,
        },
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }
}
